#include "../头文件/showjpg.h"

/**
 * @brief 使用jpg库提供的接口函数实现jpg的显示
 * 			任意位置显示任意大小的jpg
 * @param x 显示的起始位置x坐标
 * @param y 显示的起始位置y坐标
 * @param jpgpath jpeg图片路径
 * @return int 
 */
int show_anyjpg(int x, int y, const char *jpgpath)
{
	int i, j;
	int lcdfd;
	int *lcdmem;
	int show_w = 0;
	int show_h = 0;
	// 打开开发板液晶屏的驱动
	lcdfd = open("/dev/fb0", O_RDWR); // fb-->frame buffer
	if (lcdfd == -1)
	{
		perror("打开lcd失败!\n");
		return -1;
	}
	// 通过内存映射得到液晶屏的首地址
	lcdmem = mmap(NULL, 800 * 480 * 4, PROT_READ | PROT_WRITE, MAP_SHARED, lcdfd, 0);
	if (lcdmem == NULL)
	{
		perror("映射lcd失败!\n");
		return -1;
	}
	// 定义解压缩结构体变量和处理错误的结构体变量
	struct jpeg_decompress_struct mydem;
	struct jpeg_error_mgr myerr;
	mydem.err = jpeg_std_error(&myerr);
	jpeg_create_decompress(&mydem);
	FILE *jpgp;
	// 打开你要显示的jpg
	jpgp = fopen(jpgpath, "r+");
	if (jpgp == NULL)
	{
		perror("打开jpg失败!\n");
		return -1;
	}
	// 获取数据源
	jpeg_stdio_src(&mydem, jpgp);
	// 读取jpg的头信息
	jpeg_read_header(&mydem, 1);
	// printf("jpeg图片的宽是: %d\n", mydem.image_width);
	// printf("jpeg图片的高是: %d\n", mydem.image_height);
	// 开始解压缩
	jpeg_start_decompress(&mydem);
	// 定义一个指针存放一行RGB数值
	char *rgbbuf = calloc(1, mydem.image_width * 3);
	// 定义一个指针存放转换得到的一行ARGB
	int *lcdbuf = calloc(1, mydem.image_width * 4);

	show_w = (mydem.image_width + x) >= 800 ? (800 - x) : mydem.image_width;
	show_h = (mydem.image_height + y) >= 480 ? (480 - y) : mydem.image_height;
	// 解压缩成功后得到的就是jpg图片的原始RGB数值--》读取并填充到lcd上
	for (i = 0; i < mydem.image_height; i++) // 比如：图片是800*480大小
	{
		// 每次循环读取一行RGB
		jpeg_read_scanlines(&mydem, (JSAMPARRAY)&rgbbuf, 1);
		// 填充(写入)到开发板的液晶屏中
		// 将一行RGB--》转化成ARGB
		for (j = 0; j < show_w; j++)
		{
			lcdbuf[j] = 0x00 << 24 | rgbbuf[3 * j] << 16 | rgbbuf[3 * j + 1] << 8 | rgbbuf[3 * j + 2];
			// 00[0][1][2]
		}

		if (i < show_h)
			memcpy(lcdmem + (y + i) * 800 + x, lcdbuf, show_w * 4); // 在指定的位置(x,y)显示该图片
	}
	// 收尾工作
	jpeg_finish_decompress(&mydem);
	jpeg_destroy_decompress(&mydem);
	close(lcdfd);
	fclose(jpgp);
	munmap(lcdmem, 800 * 480 * 4);
	free(rgbbuf);
	free(lcdbuf);
	return 0;
}

// 在任意位置显示一张800*480缩小4倍后的jpg图片
int show_anyjpg_solv(int x, int y, const char *jpgpath)
{
	int i, j;
	int lcdfd;
	int *lcdmem;
	int jpgbuf[800 * 480];
	// 打开开发板液晶屏的驱动
	lcdfd = open("/dev/fb0", O_RDWR); // fb-->frame buffer
	if (lcdfd == -1)
	{
		perror("打开lcd失败!\n");
		return -1;
	}
	// 通过内存映射得到液晶屏的首地址
	lcdmem = mmap(NULL, 800 * 480 * 4, PROT_READ | PROT_WRITE, MAP_SHARED, lcdfd, 0);
	if (lcdmem == NULL)
	{
		perror("映射lcd失败!\n");
		return -1;
	}
	// 定义解压缩结构体变量和处理错误的结构体变量
	struct jpeg_decompress_struct mydem;
	struct jpeg_error_mgr myerr;
	mydem.err = jpeg_std_error(&myerr);
	jpeg_create_decompress(&mydem);
	FILE *jpgp;
	// 打开你要显示的jpg
	jpgp = fopen(jpgpath, "r+");
	if (jpgp == NULL)
	{
		perror("打开jpg失败! \n");
		return -1;
	}
	// 获取数据源
	jpeg_stdio_src(&mydem, jpgp);
	// 读取jpg的头信息
	jpeg_read_header(&mydem, 1);
	printf("图片的宽是：%d\n", mydem.image_width);
	printf("图片的高是：%d\n", mydem.image_height);
	// 开始解压缩
	jpeg_start_decompress(&mydem);
	// 定义一个指针存放一行RGB数值
	char *rgbbuf = calloc(1, mydem.image_width * 3);
	// 定义一个指针存放转换得到的一行ARGB
	int *lcdbuf = calloc(1, mydem.image_width * 4);
	// 解压缩成功后得到的就是jpg图片的原始RGB数值--》读取并填充到lcd上
	for (i = 0; i < mydem.image_height; i++) // 比如：图片是800*480大小
	{
		// 每次循环读取一行RGB
		jpeg_read_scanlines(&mydem, (JSAMPARRAY)&rgbbuf, 1);
		// 填充(写入)到开发板的液晶屏中
		// 将一行RGB--》转化成ARGB
		for (j = 0; j < mydem.image_width; j++)
		{
			lcdbuf[j] = 0x00 << 24 | rgbbuf[3 * j] << 16 | rgbbuf[3 * j + 1] << 8 | rgbbuf[3 * j + 2];
			// 00[0][1][2]
			jpgbuf[i * mydem.image_width + j] = lcdbuf[j];
		}

		// 在指定的位置(x,y)显示该图片
		// memcpy(lcdmem+(y+i)*800+x,lcdbuf,mydem.image_width*4);
	}
	// 切割缩小4倍图片
	int minbuf[200 * 120] = {0};

	for (j = 0; j < mydem.image_height; j++)
	{
		for (i = 0; i < mydem.image_width; i++)
		{
			if (mydem.image_height % 4 == 0 && mydem.image_width % 4 == 0)
				minbuf[j / 4 * 200 + i / 4] = jpgbuf[j * mydem.image_width + i];
		}
	}
	// 显示
	for (j = 0; j < 120; j++)
	{
		for (i = 0; i < 200; i++)
		{
			lcdmem[(j + y) * 800 + i + x] = minbuf[j * 200 + i];
		}
	}
	// 收尾工作
	jpeg_finish_decompress(&mydem);
	jpeg_destroy_decompress(&mydem);
	close(lcdfd);
	fclose(jpgp);
	munmap(lcdmem, 800 * 480 * 4);
	free(rgbbuf);
	free(lcdbuf);
	return 0;
}